package cn.itsource.basic.interceptor;

import cn.itsource.basic.annotation.PreAuthorize;
import cn.itsource.basic.jwt.*;
import cn.itsource.system.mapper.PermissionMapper;
import cn.itsource.user.domain.Logininfo;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Component;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.HandlerInterceptor;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;
import java.security.PublicKey;
import java.util.List;
import java.util.concurrent.TimeUnit;

/*
* 检查所有请求是否携带了token的拦截器
* */
@Component//通用注解 交给Spring管理
public class LoginInterceptor implements HandlerInterceptor {

    @Autowired
    private RedisTemplate redisTemplate;

    @Autowired
    private PermissionMapper permissionMapper;

    /*
    *登录以后 加入权限检查
    * 1.判断是否是主站用
    * 如果是 则放行
    * 2.如果不是
    *   检查当前用户是否有访问当前请求资源的权限
    *       2.1 查出当前请求需要什么权限
    *       2.2 查询当前用户有什么权限
    *       2.3 如果当前用户拥有的权限中包含所需要的权限 则放行，否则响应无权限
    *
    * */
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        /*
        * 1.先从请求头中取U-TOKEN
        * 2.如果没有 响应success:false message:noLogin
        * 3.如果有
        *   3.1 查redis中是否有登录信息
        *       redis中有登录信息 放行
        *       redis中没有登录信息 响应success:false message:noLogin
        *
        * */

        try {
//         1.先从请求头中取U-TOKEN
            String token = request.getHeader(LoginContext.JWT_TOKEN_HEADER_NAME);
//         2.如果没有 响应success:false message:noLogin
            if (!StringUtils.isEmpty(token)){//只有在请求头里面携带了token并且根据token从redis中查出了登录信息才会放行
                //           3.1 查redis中是否有登录信息
    //            Object logininfo = redisTemplate.opsForValue().get(token);这里就不再去redis查询用户信息 权限信息 直接从jwt token里面去解析出来
                JSONObject logininfo = LoginContext.getCurrentUser(token);
                if (logininfo != null) {
                    //登录以后 加入权限检查
                    //1.判断是否是主站用户
                    Logininfo loigininfoTemp = JSON.parseObject(JSON.toJSONString(logininfo), Logininfo.class);
                    //如果是 则放行
                    if (!loigininfoTemp.getType()) {
                        //2.如果不是
                        //检查当前用户是否有访问当前请求资源的权限
                        //2.1 查出当前请求需要什么权限
                        HandlerMethod method = (HandlerMethod)handler;
                        PreAuthorize preAuthorize = method.getMethodAnnotation(PreAuthorize.class);
                        if (preAuthorize != null){
                            String needPerm = preAuthorize.value();//这个方法需要什么权限
                            //2.2 查询当前用户有什么权限
    //                        List<String> ownPerms = permissionMapper.loadPermissionByLonginId(loigininfoTemp.getId());权限直接从payLoadData去取
                            List<String> ownPerms = LoginContext.getCurrentUserPermissions(token);
                            //2.3 如果当前用户拥有的权限中包含所需要的权限 则放行，否则响应无权限
                            if (!ownPerms.contains(needPerm)){//needPerm有没有包含在ownPerms集合里面
                                PrintWriter writer =    response.getWriter();
                                writer.write("{\"success\":false,\"message\":\"noPermission\"}");
                                writer.flush();
                                writer.close();
                                return false;
                            }
                        }

                    }

                    //刷新过期时间
    //                redisTemplate.opsForValue().set(token, logininfo, 30, TimeUnit.MINUTES);
                    return true;
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }

        response.setCharacterEncoding("utf-8");//设置字符编码集
        response.setContentType("application/json;charset=utf-8");//设置响应的文本类型和字符编码集
        //获取输出流
        PrintWriter writer =    response.getWriter();
        writer.write("{\"success\":false,\"message\":\"noLogin\"}");
        writer.flush();
        writer.close();
        return false;//不放行

    }
}
